package com.aek.aekdroid;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.TimeZone;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.net.Uri;

import com.aek.aekdroid.data.CalendarMatch;
import com.aek.aekdroid.data.IDbConstants;
import com.aek.aekdroid.data.MatchData;

public class Calendar {
	public static final String TAG = "Calendar";
	Activity act;
	UserCalendar[] calendars;
	String[] calendarNames;
	public String selectedCalendarId;

	public Calendar(Activity act) {
		this.act = act;
	}

	public String getCalendarUriBase() {
		String calendarUriBase = null;
		Uri calendars = Uri.parse("content://calendar/calendars");
		Cursor managedCursor = null;
		try {
			managedCursor = act.managedQuery(calendars, null, null, null, null);
		} catch (Exception e) {
			// eat
		}

		if (managedCursor != null) {
			calendarUriBase = "content://calendar/";
		} else {
			calendars = Uri.parse("content://com.android.calendar/calendars");
			try {
				managedCursor = act.managedQuery(calendars, null, null, null, null);
			} catch (Exception e) {

			}

			if (managedCursor != null) {
				calendarUriBase = "content://com.android.calendar/";
			}

		}

		return calendarUriBase;
	}

	public void getCalendars() {
		String[] projection = new String[] { "_id", "name" };
		String selection = "visible=1";
		String path = "calendars";

		Cursor managedCursor = getCalendarManagedCursor(projection, selection, path);
		if (managedCursor == null) {
			return;
		}
		calendars = new UserCalendar[managedCursor.getCount()];
		calendarNames = new String[managedCursor.getCount()];
		if (managedCursor != null && managedCursor.moveToFirst()) {

			MyLog.i(TAG, "Listing Selected Calendars Only");

			int nameColumn = managedCursor.getColumnIndex("name");
			int idColumn = managedCursor.getColumnIndex("_id");
			int i = 0;
			do {
				String calName = managedCursor.getString(nameColumn);
				String calId = managedCursor.getString(idColumn);
				MyLog.i(TAG, "Found Calendar '" + calName + "' (ID=" + calId + ")");
				calendars[i] = new UserCalendar(calId, calName);
				calendarNames[i] = calName;
				i++;

			} while (managedCursor.moveToNext());
		} else {
			MyLog.i(TAG, "No Calendars");
		}

		return;

	}

	private Cursor getCalendarManagedCursor(String[] projection, String selection, String path) {
		Uri calendars = Uri.parse("content://calendar/" + path);

		Cursor managedCursor = null;
		try {
			managedCursor = act.managedQuery(calendars, projection, selection, null, null);
		} catch (IllegalArgumentException e) {
			MyLog.w(TAG, "Failed to get provider at [" + calendars.toString() + "]");
		}

		if (managedCursor == null) {
			// try again
			calendars = Uri.parse("content://com.android.calendar/" + path);
			try {
				managedCursor = act.managedQuery(calendars, projection, selection, null, null);
			} catch (IllegalArgumentException e) {
				MyLog.w(TAG, "Failed to get provider at [" + calendars.toString() + "]");
			} catch (SQLiteException e) {
				MyLog.w(TAG, "No visible column , pre ICS version");
				selection = "selected=1";
				managedCursor = act.managedQuery(calendars, projection, selection, null, null);
			}
		}
		return managedCursor;
	}

	public String selectCalendar(final AekDroidApplication aek, final boolean checked) {
		if (calendars == null) {
			AlertDialog.Builder builder = new AlertDialog.Builder(act);
			builder.setMessage(act.getString(R.string.calendar_noCalendars)).setCancelable(false)
					.setNegativeButton(act.getString(R.string.ok), new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int id) {
							dialog.cancel();
						}
					});
			AlertDialog alert = builder.create();
			alert.show();
			return null;
		} else {
			AlertDialog.Builder builder = new AlertDialog.Builder(act);
			builder.setTitle(act.getString(checked ? R.string.calendar_selectCalendar : R.string.calendar_deleteFromCalendar));
			builder.setItems(calendarNames, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int item) {
					String selCalendarId = getCalendarId(calendars[item].name);
					if (selCalendarId != null) {
						MyLog.d(TAG, "Select calendar " + selCalendarId);
						Calendar.this.selectedCalendarId = selCalendarId;
						if (selectedCalendarId == null) {
							MyLog.d(TAG, "Calendar is not selected");
						} else {
							if (checked) {
								MyLog.d(TAG, "Calendar is selected, getting matches");
								aek.setSelectedCalendarId(selectedCalendarId);
								updateCalendar(aek);
							} else {
								MyLog.d(TAG, "Calendar is removed, getting matches");
								aek.setSelectedCalendarId(null);
								deleteCalendar(aek);
							}
						}
					}
				}

			});
			AlertDialog alert = builder.create();
			alert.show();
		}
		return "";
	}

	private String getCalendarId(String name) {
		MyLog.d(TAG, "Searching for Calendar " + name);
		for (int i = 0; i < calendars.length; i++) {
			UserCalendar cal = calendars[i];
			if (name.equals(cal.name)) {
				MyLog.d(TAG, "Found Calendar " + cal.id);
				return cal.id;
			}
		}
		return null;
	}

	public int deleteCalendar(AekDroidApplication aek) {
		MatchData db = aek.getMatchData();
		int deletes = 0;
		ArrayList<CalendarMatch> matches = db.getCalendarMatches();
		for (Iterator<CalendarMatch> iterator = matches.iterator(); iterator.hasNext();) {
			CalendarMatch match = iterator.next();
			boolean deleted = deleteFromCalendar(aek, match.calId);
			if (deleted) {
				deletes++;
				ContentValues values = new ContentValues();
				values.put(IDbConstants.MATCHES_C_CALENDAR_ID, "");
				db.update(values, match.id);
			}
		}
		return deletes;
	}

	public int updateCalendar(AekDroidApplication aek) {
		int updates = 0;
		MatchData db = aek.getMatchData();
		ArrayList<CalendarMatch> matches = db.getCalendarMatches();
		for (Iterator<CalendarMatch> iterator = matches.iterator(); iterator.hasNext();) {
			CalendarMatch match = iterator.next();
			Uri uri = null;
			if (match.datetime > System.currentTimeMillis()) {
				if (match.deleted == 0) {
					uri = insertInCalendar(aek, match);
					if (uri != null) {
						updates++;
						ContentValues values = new ContentValues();
						values.put(IDbConstants.MATCHES_C_CALENDAR_ID, uri.getLastPathSegment());
						db.update(values, match.id);
						MyLog.d(TAG, uri.toString());
					}
				} else {
					boolean deleted = deleteFromCalendar(aek, match.calId);
					if (deleted) {
						ContentValues values = new ContentValues();
						values.put(IDbConstants.MATCHES_C_CALENDAR_ID, "");
						db.update(values, match.id);
					}
				}
			}
		}
		return updates;
	}

	public boolean deleteFromCalendar(AekDroidApplication aek, String id) {

		Uri eventsUri = Uri.parse(getCalendarUriBase() + "events");
		if (Helper.isNumeric(id)) {
			Uri eventUri = ContentUris.withAppendedId(eventsUri, Long.parseLong(id));
			aek.getContentResolver().delete(eventUri, null, null);
			MyLog.i(TAG, "Deleted " + id + " calendar entry.");
			return true;
		}
		return false;

	}

	private Uri insertInCalendar(AekDroidApplication aek, CalendarMatch match) {

		ContentValues event = new ContentValues();
		String calId = aek.getSelectedCalendarId();
		MyLog.d(TAG, "Inserting/Updating " + match + " in calendar " + calId);
		if (calId == null) {
			return null;
		}
		event.put("calendar_id", calId);
		event.put("title", match.homeTeam + "-" + match.awayTeam);
		event.put("description", match.tournament + ":\n" + match.homeTeam + "-" + match.awayTeam);
		event.put("eventLocation", match.stadium);

		long startTime = match.datetime;
		long endTime = match.datetime + 1000 * 60 * 60 * 2;
		TimeZone timezone = TimeZone.getTimeZone("GMT+3:00");

		event.put("dtstart", startTime);
		event.put("dtend", endTime);

		event.put("allDay", 0); // 0 for false, 1 for true
		event.put("eventStatus", 1);
		event.put("hasAlarm", 0); // 0 for false, 1 for true
		event.put("eventTimezone", "GMT+3:00");
		Uri eventsUri = Uri.parse(getCalendarUriBase() + "events");
		MyLog.d(TAG, "Insert uri: " + eventsUri);
		if (match.calId == null || !isValidCalId(aek, match.calId, eventsUri)) {
			MyLog.d(TAG, "New or invalid entry.Inserting new");
			Uri insertedUri = aek.getContentResolver().insert(eventsUri, event);
			MyLog.d(TAG, "Inserted uri: " + insertedUri);
			return insertedUri;
		} else {
			if (Helper.isNumeric(match.calId)) {
				Uri eventUri = ContentUris.withAppendedId(eventsUri, Long.parseLong(match.calId));

				int insertedUri = aek.getContentResolver().update(eventUri, event, null, null);
				MyLog.d(TAG, "Updated uri: " + eventUri);
				return null;
			}
			return null;
		}

	}

	private boolean isValidCalId(AekDroidApplication aek, String id, Uri uri) {
		Cursor c = aek.getContentResolver().query(uri, null, "_id = ? ", new String[] { id }, null);
		return c.moveToFirst();
	}

	class UserCalendar {
		public String id;
		public String name;

		public UserCalendar(String id, String name) {
			this.id = id;
			this.name = name;
		}

		@Override
		public String toString() {
			return name;
		}
	}

}
